package com.xxcxcxcx.jobsystem.common.Job.Blacksmith;

import com.xxcxcxcx.jobsystem.Main;
import com.xxcxcxcx.jobsystem.PlayerSaveData;
import com.xxcxcxcx.jobsystem.common.Job.JobBase;
import com.xxcxcxcx.jobsystem.common.JobsClass;
import com.xxcxcxcx.jobsystem.common.capability.JobCapability;
import com.xxcxcxcx.jobsystem.common.capability.JobCapabilityProvider;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.*;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.util.LazyOptional;

import java.util.Random;

public class Blacksmith extends JobBase {
    public static String Job= JobsClass.Blacksmith;
    public static String MakeTool= Main.MOD_ID+".tool.maketool";
    public static String ToolLevel="toollevel";
    public static String Damage="damage";
    public static String DamageSpeed="damagespeed";
    public static String Speed="speed";
    public static String Durable="durable";
    public static String Creater="Creater";
    public static String CreaterLevel="CreaterLevel";
    public static String ToolUnIdentification = "UnIdentification";
    public static String ToolKind = "ToolKind";
    public static String[] ToolLevels= {"inferior","ordinary","quality","epic","legend"};
    public static String[] ToolKinds= {"light","normal","heavy","magic","legend"};
    public static Attribute[] defenseattributes={Attributes.ARMOR,Attributes.ARMOR_TOUGHNESS,Attributes.KNOCKBACK_RESISTANCE,Attributes.MAX_HEALTH,Attributes.MOVEMENT_SPEED};
    public static Attribute[] attackattributes={Attributes.ATTACK_DAMAGE,Attributes.ATTACK_SPEED,Attributes.ATTACK_KNOCKBACK};

    public static int RepairMaterialCost(Player player){
        int num=4;
        num+=GetUP(player);
        return num;
    }
    public static int RepairDurabilityBonus(Player player,int count){
        int num=(int)Math.round(count*1.25);
        num-=GetUP(player)*(int)Math.round(count/2.0);
        return num;
    }
    private static int GetUP(Player player){
        LazyOptional<JobCapability> capability = JobCapabilityProvider.getPlayerData(player);
        if(!capability.isPresent()) {
            return 2;
        }
        PlayerSaveData playerSaveData = capability.orElse(null);
        int Joblevel =playerSaveData.getLevel(Job);
        int num;
        if(Joblevel==0){
            num=2;
        }else if(Joblevel<4){
            num=1;
        }else if(Joblevel<7){
            num=0;
        }else if(Joblevel<9){
            num=-1;
        }else{
            num=-2;
        }
        return num;
    }

    public static void GetTools(Player player, ItemStack itemStack) {
        LazyOptional<JobCapability> capability = JobCapabilityProvider.getPlayerData(player);
        if(!capability.isPresent()) {
            return;
        }
        PlayerSaveData playerSaveData = capability.orElse(null);
        int smithlevel=playerSaveData.getLevel(Job);
        ItemSmithIn smithIn =(ItemSmithIn)itemStack.getItem();
        smithIn.setCreater(itemStack,player,smithlevel);
    }
    public static void IdentificationTool(Player player, ItemStack itemStack){
        if(!(itemStack.getItem() instanceof TieredItem||itemStack.getItem() instanceof ArmorItem))return;
        int smithlevel=itemStack.getOrCreateTagElement(Main.MOD_ID).getInt(MakeTool+CreaterLevel);
        ItemStack newitemstack=itemStack.copy();
        newitemstack.getOrCreateTagElement(Main.MOD_ID).remove(MakeTool+ToolLevel);
        if(smithlevel==0){
            CreatTools(newitemstack,player,0,newitemstack.getCount());
        }else if(smithlevel<4){
            double r=player.getRandom().nextDouble();
            if(r<smithlevel*0.2){
                CreatTools(newitemstack,player,1,newitemstack.getCount());
            }else{
                CreatTools(newitemstack,player,0,newitemstack.getCount());
            }
        }else if(smithlevel<7){
            double r=player.getRandom().nextDouble();
            if(r<(smithlevel-4)*0.2){
                CreatTools(newitemstack,player,2,newitemstack.getCount());
            }else if(r<(1-(7-smithlevel)*0.05)){
                CreatTools(newitemstack,player,1,newitemstack.getCount());
            }else{
                CreatTools(newitemstack,player,0,newitemstack.getCount());
            }
        }else if(smithlevel<10){
            double r=player.getRandom().nextDouble();
            if(r<(smithlevel-6)*0.1){
                CreatTools(newitemstack,player,3,newitemstack.getCount());
            }else if(r<((smithlevel-4)*0.15+0.1)){
                CreatTools(newitemstack,player,2,newitemstack.getCount());
            }else{
                CreatTools(newitemstack,player,1,newitemstack.getCount());
            }
        }else{
            double r=player.getRandom().nextDouble();
            if(r<0.1){
                CreatTools(newitemstack,player,4,newitemstack.getCount());
            }else if(r<Math.min((smithlevel-6)*0.1,0.9)){
                CreatTools(newitemstack,player,3,newitemstack.getCount());
            }else if(r<(Math.min((smithlevel-4)*0.15+0.1,0.95))){
                CreatTools(newitemstack,player,2,newitemstack.getCount());
            }else{
                CreatTools(newitemstack,player,1,newitemstack.getCount());
            }
        }
        if(itemStack.getItem() instanceof ArmorItem){
            if(smithlevel==0){
                if(player.getRandom().nextBoolean())CreatToolKind(newitemstack, 0);
                else CreatToolKind(newitemstack, 2);
            }else if(smithlevel<4){
                if(player.getRandom().nextBoolean())CreatToolKind(newitemstack, 0);
                else CreatToolKind(newitemstack, 2);
            }else if(smithlevel<7){
                if(player.getRandom().nextFloat()<0.1f)CreatToolKind(newitemstack, 1);
                else if(player.getRandom().nextBoolean())CreatToolKind(newitemstack, 0);
                else CreatToolKind(newitemstack, 2);
            }else if(smithlevel<10){
                if(player.getRandom().nextFloat()<0.05f)CreatToolKind(newitemstack, 3);
                else if(player.getRandom().nextFloat()<0.2f)CreatToolKind(newitemstack, 1);
                else if(player.getRandom().nextBoolean())CreatToolKind(newitemstack, 0);
                else CreatToolKind(newitemstack, 2);
            }else{
                if(player.getRandom().nextFloat()<0.01f)CreatToolKind(newitemstack, 4);
                else if(player.getRandom().nextFloat()<0.1f)CreatToolKind(newitemstack, 3);
                else if(player.getRandom().nextFloat()<0.2f)CreatToolKind(newitemstack, 1);
                else if(player.getRandom().nextBoolean())CreatToolKind(newitemstack, 0);
                else CreatToolKind(newitemstack, 2);
            }
        }
        if(player.getInventory().getSlotWithRemainingSpace(newitemstack)!=-1||player.getInventory().getFreeSlot()!=-1){
            player.addItem(newitemstack);
            itemStack.setCount(0);
        }else{
            Block.popResource(player.level,new BlockPos(player.position()), newitemstack);
            itemStack.setCount(0);
        }
    }
    public static void CreatTools(ItemStack itemStack,Player player,int GLevel,int num2){
        ItemSmithIn smithIn =(ItemSmithIn)itemStack.getItem();
        LazyOptional<JobCapability> capability = JobCapabilityProvider.getPlayerData(player);
        if(!capability.isPresent()) {
            return;
        }
        PlayerSaveData playerSaveData = capability.orElse(null);
        int JobLevel = playerSaveData.getLevel(Job);
        float num=1;
        if(itemStack.getItem() instanceof TieredItem tieredItem){
            if(tieredItem.getTier()== Tiers.WOOD){
                if(JobLevel==0)num = 2;
                else num=0;
            }
            else if(tieredItem.getTier()== Tiers.STONE){
                if(JobLevel==0)num = 4;
                else if(JobLevel<4)num = 2;
                else num=0;
            }
            else if(tieredItem.getTier()== Tiers.GOLD){
                if(JobLevel<7)num = 5;
                else num=0;
            }
            else if(tieredItem.getTier()== Tiers.IRON){
                if(JobLevel<7)num = 4;
                else num=0;
            }
            else if(tieredItem.getTier()== Tiers.DIAMOND){
                if(JobLevel<7)num = 10;
                else if(JobLevel<10)num = 2;
                else num=0;
            }
            else if(tieredItem.getTier()== Tiers.NETHERITE){
                if(JobLevel<10)num = 4;
                else num=0;
            }
            UpExperience(player,(GLevel+1)*num, Job);
        }
        else if(itemStack.getItem() instanceof ArmorItem armorItem){
            if(armorItem.getMaterial() == ArmorMaterials.GOLD){
                if(JobLevel==0)num = 22;
                else if(JobLevel<7)num = 4;
                else num=0;
            }
            else if(armorItem.getMaterial() == ArmorMaterials.CHAIN){
                if(JobLevel==0)num = 12;
                else if(JobLevel < 7)num =3;
                else num=0;
            }
            else if(armorItem.getMaterial() == ArmorMaterials.IRON){
                if(JobLevel==0)num = 20;
                else if(JobLevel < 7)num =7;
                else num=0;
            }
            else if(armorItem.getMaterial() == ArmorMaterials.DIAMOND){
                if(JobLevel<7)num = 30;
                else if(JobLevel<10)num = 7;
                else num=0;
            }
            else if(armorItem.getMaterial() == ArmorMaterials.NETHERITE){
                if(JobLevel<10)num = 48;
                else num=0;
            }
            UpExperience(player,(GLevel+1)*num, Job);
        }
        itemStack.getOrCreateTagElement(Main.MOD_ID).putString(MakeTool+ToolLevel,ToolLevels[GLevel]);
        Random r=player.getRandom();
        if(itemStack.getItem() instanceof TieredItem){
            switch (GLevel) {
                case 0 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(0.4f, 0.5f));
                    smithIn.setNewSpeed(itemStack, r.nextFloat(0.4f, 0.5f));
                    smithIn.setNewDamage(itemStack, r.nextFloat(0.4f, 0.5f));
                    smithIn.setNewDamageSpeed(itemStack, r.nextFloat(1.2f, 1.3f));
                }
                case 1 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(0.6f, 0.8f));
                    smithIn.setNewSpeed(itemStack, r.nextFloat(0.6f, 0.8f));
                    smithIn.setNewDamage(itemStack, r.nextFloat(0.6f, 0.8f));
                    smithIn.setNewDamageSpeed(itemStack, r.nextFloat(1.1f, 1.2f));
                }
                case 2 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(0.9f, 1.1f));
                    smithIn.setNewSpeed(itemStack, r.nextFloat(0.9f, 1.1f));
                    smithIn.setNewDamage(itemStack, r.nextFloat(0.9f, 1.1f));
                    smithIn.setNewDamageSpeed(itemStack, r.nextFloat(0.9f, 1.1f));
                }
                case 3 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(1.1f, 1.3f));
                    smithIn.setNewSpeed(itemStack, r.nextFloat(1.1f, 1.3f));
                    smithIn.setNewDamage(itemStack, r.nextFloat(1.1f, 1.3f));
                    smithIn.setNewDamageSpeed(itemStack, r.nextFloat(0.7f, 0.9f));
                }
                case 4 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(1.3f, 1.5f));
                    smithIn.setNewSpeed(itemStack, r.nextFloat(1.3f, 1.5f));
                    smithIn.setNewDamage(itemStack, r.nextFloat(1.3f, 1.5f));
                    smithIn.setNewDamageSpeed(itemStack, r.nextFloat(0.5f, 0.7f));
                }
            }
        }
        else if(itemStack.getItem() instanceof ArmorItem){
            switch (GLevel) {
                case 0 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(0.4f, 0.8f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR, r.nextFloat(0.4f, 0.5f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR_TOUGHNESS, r.nextFloat(0.4f, 0.5f));
                    smithIn.setEffect(itemStack, Attributes.KNOCKBACK_RESISTANCE, r.nextFloat(0.4f, 0.5f));
                }
                case 1 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(0.4f, 0.8f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR, r.nextFloat(0.6f, 0.8f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR_TOUGHNESS, r.nextFloat(0.6f, 0.8f));
                    smithIn.setEffect(itemStack, Attributes.KNOCKBACK_RESISTANCE, r.nextFloat(0.6f, 0.8f));
                }
                case 2 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(0.8f, 1.2f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR, r.nextFloat(0.9f, 1.1f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR_TOUGHNESS, r.nextFloat(0.9f, 1.1f));
                    smithIn.setEffect(itemStack, Attributes.KNOCKBACK_RESISTANCE, r.nextFloat(0.9f, 1.1f));
                }
                case 3 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(1.0f, 1.4f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR, r.nextFloat(1.1f, 1.3f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR_TOUGHNESS, r.nextFloat(1.1f, 1.3f));
                    smithIn.setEffect(itemStack, Attributes.KNOCKBACK_RESISTANCE, r.nextFloat(1.1f, 1.3f));
                }
                case 4 -> {
                    smithIn.setNewDurable(itemStack, r.nextFloat(1.5f, 2.0f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR, r.nextFloat(1.3f, 1.5f));
                    smithIn.setEffect(itemStack, Attributes.ARMOR_TOUGHNESS, r.nextFloat(1.3f, 1.5f));
                    smithIn.setEffect(itemStack, Attributes.KNOCKBACK_RESISTANCE, r.nextFloat(1.3f, 1.5f));
                }
            }
        }
    }
    public static void CreatToolKind(ItemStack itemStack, int GLevel){
        ItemSmithIn smithIn =(ItemSmithIn)itemStack.getItem();
        smithIn.setKind(itemStack,ToolKinds[GLevel]);
    }
}
